package com.cnbot.aimolib;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.aimall.core.ImoSDK;
import com.cnbot.aimolib.bean.AimoFrameData;
import com.cnbot.aimolib.bean.AimoRawFaceData;
import com.cnbot.aimolib.db.AimoFaceDbData;
import com.cnbot.aimolib.db.AimoFaceDbManager;
import com.cnbot.aimolib.detect.DetectTask;
import com.cnbot.aimolib.recognize.RecognizeTask;

import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * @author ytf
 * Created by on 2021/06/01 14:12
 */
public class AimoEngine {

    private DetectionTrackerCore mCore;

    private static AimoEngine instance;
    private ExecutorService pool;

    public static AimoEngine getInstance(){
        if(instance == null){
            synchronized(AimoEngine.class){
                if(instance == null){
                    instance = new AimoEngine();
                }
            }
        }
        return instance;
    }

    private volatile AtomicBoolean flag = new AtomicBoolean(false);
    private Callback mCallback;

    public void init(final Context context, final String key, final String modelDir, final Callback callback){
        if(!flag.getAndSet(true)){
            mCallback = callback;
            pool = Executors.newFixedThreadPool(2);
            mCore = new DetectionTrackerCore(2, 1);

            pool.submit(new Runnable() {
                @Override
                public void run() {
                    ImoSDK.init(context, key, modelDir, new ImoSDK.OnInitListener() {
                        @Override
                        public void onInitSuccess(String var1, long var2) {
                            if(mCore.canWork()){
                                callback.onInitState(true, "");
                                Log.e("s", "aimo初始化成功：" + var1 + ", " + var2);
                            }else{
                                callback.onInitState(false, "内核初始化失败");
                            }
                        }

                        @Override
                        public void onInitError(int var1, String var2) {
                            callback.onInitState(false, "aimo sdk初始化失败");
                            Log.e("s", "初始化失败：" + var1 + ", " + var2);
                        }
                    });
                }
            });
        }
    }

    public DetectionTrackerCore getCore(){
        return mCore;
    }

    public void destroy(){
        mCore.release();
        ImoSDK.init(null, null, null, null);
    }

    public void syncLocaleDb(AimoFaceDbData afterSetUserId){
        AimoFaceDbManager.getInstance().insertOrReplace(afterSetUserId);
    }

    public List<AimoFaceDbData> getAllFace(){
        return AimoFaceDbManager.getInstance().listAll();
    }

    public void delete(AimoFaceDbData d){
        String p = d.path;
        File f = new File(p);
        if(f.exists()){
            f.delete();
        }
        AimoFaceDbManager.getInstance().delete(d);
    }

    public void deleteByUserId(String userId){
        AimoFaceDbData exist = AimoFaceDbManager.getInstance().querFaceByUserId(userId);
        if(exist != null){
            //图片也删除
            String p = exist.path;
            File f = new File(p);
            if(f.exists()){
                f.delete();
            }
        }
        AimoFaceDbManager.getInstance().deleteByUserId(userId);
    }

    public AimoFaceDbData queryFaceByUserId(String userid){
        return AimoFaceDbManager.getInstance().querFaceByUserId(userid);
    }

    public AimoFaceDbData detectBitmapAndRecord(File bmpFile, String userId){
        Bitmap bmp = BitmapFactory.decodeFile(bmpFile.getAbsolutePath());
        List<AimoRawFaceData> list = mCore.detectFromBmp(bmp);
        if(list != null && list.size() != 0)
        {
            int size = list.size();
            AimoRawFaceData target;
            if(size > 1){
                Collections.sort(list, new Comparator<AimoRawFaceData>()
                {
                    @Override
                    public int compare(AimoRawFaceData o1, AimoRawFaceData o2)
                    {
                        float o1area = o1.getRect().width() * o1.getRect().height();
                        float o2area = o2.getRect().width() * o2.getRect().height();
                        return Float.compare(o1area, o2area);
                    }
                });
                target = list.get(size-1);
            }else{
                target = list.get(0);
            }
            AimoFaceDbData preInsert = new AimoFaceDbData(null, target.faceFeature.getFeatures(), bmpFile.getAbsolutePath(), userId);
            long id = AimoFaceDbManager.getInstance().insertOrReplace(preInsert);
            preInsert._id = (int)id;
            return preInsert;
        }
        return null;
    }

    private DetectTask mDetectTask;
    public synchronized void startDetectTask(DetectTask task){
        if(mDetectTask == null || !mDetectTask.isActive()){
            mDetectTask = task;
            pool.submit(mDetectTask);
        }
    }

    public boolean isBusy(){
        return (mDetectTask != null && mDetectTask.isActive())
                || (mRecognizeTask != null && mRecognizeTask.isActive());
    }

    public synchronized void stopDetectTask(){
        if(mDetectTask != null){
            mDetectTask.exit();
            mDetectTask = null;
        }
    }

    private RecognizeTask mRecognizeTask;
    public synchronized void startRecognizeTask(RecognizeTask task){
        if(mRecognizeTask == null || !mRecognizeTask.isActive()){
            mRecognizeTask = task;
            pool.submit(mRecognizeTask);
        }
    }

    public synchronized void stopRecognizeTask(){
        if(mRecognizeTask != null){
            mRecognizeTask.exit();
            mRecognizeTask = null;
        }
    }

    public void feedDetectData(byte[] data, int previewWid, int previewHeight){
        if(mDetectTask != null && mDetectTask.isActive()){
            byte[] copy = new byte[data.length];
            System.arraycopy(data, 0, copy, 0, data.length);
            mDetectTask.post(new AimoFrameData(copy, previewWid, previewHeight));
        }
        if(mRecognizeTask != null && mRecognizeTask.isActive()){
            byte[] copy = new byte[data.length];
            System.arraycopy(data, 0, copy, 0, data.length);
            mRecognizeTask.post(new AimoFrameData(copy, previewWid, previewHeight));
        }
    }

    public void shutdown(){
        if(flag.getAndSet(false)){
            mCore.release();
        }
    }

    public interface Callback{
        void onInitState(boolean ok, String reason);
    }
}
